using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DnsService.Events;
using DnsService.Interfaces;
using DnsService.Models;
using DnsService.Services;
using DnsService.Utilities;
using LocalDnsSdk.Commands;
using LocalDnsSdk.Formatting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NLog;


namespace DnsService
{
    /// <summary>
    /// DNS服务主要功能类，提供DNS服务的初始化和管理功能
    /// 作者：huobing
    /// </summary>
    public class DnsServiceManager
    {
        private IDnsService? _dnsService;
        private Logger _logger = LogManager.GetCurrentClassLogger();
        private IDnsConfigManager? _configManager;
        private DnsService.Utilities.NetworkDnsMonitor? _dnsMonitor;
        private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
        private CancellationTokenSource? _cancellationTokenSource;
        private bool _isRunning = false;
        // 新增：Named Pipes命令服务端
        private DnsService.IPC.NamedPipeCommandServer? _pipeServer;

        /// <summary>
        /// 运行DNS服务的主要方法
        /// </summary>
        /// <param name="options">DNS服务选项</param>
        /// <returns>是否启动成功</returns>
        /// <summary>
        /// 运行DNS服务的主要方法
        /// </summary>
        /// <param name="options">DNS服务选项</param>
        /// <returns>是否启动成功</returns>
        public bool Run(DnsServiceOptions options)
        {
            Console.Title = "DNS Service - Toolbox";
            // 这里先使用Console，因为_logger还未初始化
            _logger.Info("=== DNS Service 启动中 ===");

            try
            {
                // 初始化选项
                DnsServiceOptions _options = options ?? new DnsServiceOptions();
                
                // 初始化组件
                InitializeComponents(_options);
                
                // 设置控制台事件处理
                SetupConsoleHandlers();
                
                // 启动DNS服务
                if (StartDnsService(_options))
                {
                    _isRunning = true;
                    _logger.Info("DNS服务启动成功");
                    
                    // 等待关闭信号
                    WaitForShutdown();
                    
                    _isRunning = false;
                    return true;
                }
                else
                {
                    _logger.Error("DNS服务启动失败");
                    return false;
                }
            }
            catch (Exception ex)
            {
                // 如果_logger已初始化则使用它，否则使用Console
                _logger.Error($"启动DNS服务时发生严重错误: {ex.Message}", ex);
                return false;
            }
            finally
            {
                // 清理资源
                Cleanup();
                // 这里使用Console，因为这是最后一条消息
                _logger.Info("=== DNS Service 已停止 ===");
            }
        }

        /// <summary>
        /// 解析命令行参数
        /// </summary>
        /// <param name="args">命令行参数数组</param>
        /// <returns>DNS服务选项</returns>
        private DnsServiceOptions ParseCommandLineArgs(string[] args)
        {
            var opts = new DnsServiceOptions();
            if (args == null || args.Length == 0) return opts;
            for (int i = 0; i < args.Length; i++)
            {
                var a = args[i];
                if (string.Equals(a, "-p", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "--port", StringComparison.OrdinalIgnoreCase))
                {
                    if (i + 1 < args.Length && int.TryParse(args[i + 1], out var port) && port > 0 && port <= 65535)
                    {
                        opts.Port = port;
                        i++; // skip value
                    }
                }
            }
            return opts;
        }




        /// <summary>
        /// 初始化组件
        /// </summary>
        /// <param name="options">DNS服务选项</param>
        private void InitializeComponents(DnsServiceOptions options)
        {
            try
            {
                // 创建配置管理器
                _configManager = new DnsConfigManager();
                
                // 加载配置
                var config = _configManager.Config;
                
                // 应用CLI覆盖（当前仅支持端口）- 只有明确指定了-p参数时才覆盖配置
                if (options != null && options.IsPortSpecified && options.Port > 0)
                {
                    _logger.Info($"使用命令行指定的端口: {options.Port}，将覆盖配置文件设置");
                    config.Port = options.Port;
                    _configManager.SaveConfig(config);
                }
                
                // 使用Logger记录配置加载信息
                _logger.Debug("=== 配置加载调试信息 ===");
                _logger.Debug($"配置文件路径: Conf/DNSService.conf");
                _logger.Debug($"IsEnabled: {config.IsEnabled}");
                _logger.Debug($"Port: {config.Port}");
                _logger.Debug($"上游DNS服务器数量: {config.UpstreamDnsServers?.Count ?? 0}");
                if (config.UpstreamDnsServers != null)
                {
                    foreach (var server in config.UpstreamDnsServers)
                    {
                        _logger.Debug($"  - {server}");
                    }
                }
                _logger.Debug("=== 配置调试信息结束 ===");
                
                // 创建DNS服务
                _dnsService = new DnsService.Services.LocalDnsService();
                
                // 启动网络DNS监控器并订阅事件
                _dnsMonitor = new NetworkDnsMonitor();
                _dnsMonitor.DnsServersUpdated += (s, eargs) =>
                {
                    var added = eargs.AddedDnsServers?.Count ?? 0;
                    var removed = eargs.RemovedDnsServers?.Count ?? 0;
                    if (added == 0 && removed == 0)
                    {
                        _logger.Debug("网络DNS无变化，跳过更新");
                        return;
                    }
                    _logger.Info($"网络DNS更新：新增 {added}，移除 {removed}");
                    if ((eargs.AggregatedDnsServers?.Count ?? 0) > 0)
                    {
                        _dnsService?.UpdatePreferredUpstreamDnsServers(eargs.AggregatedDnsServers);
                    }
                    if (removed > 0)
                    {
                        _dnsService?.ClearCacheByUpstreamDnsServers(eargs.RemovedDnsServers);
                    }
                };
                _dnsMonitor.Start();
                
                // 设置DNS记录
                foreach (var record in config.DnsRecords.Values)
                {
                    _dnsService.AddDnsRecord(record.Domain, record.IP, record.RecordType, record.Ttl, record.Description);
                }
                
                // 启动配置文件监听
                _configManager.StartWatching();
                
                _logger.Info("组件初始化完成");
            }
            catch (Exception ex)
            {
                throw new Exception($"初始化组件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 设置控制台事件处理
        /// </summary>
        private void SetupConsoleHandlers()
        {
            try
            {
                _cancellationTokenSource = new CancellationTokenSource();
                
                // 设置Ctrl+C事件处理
                Console.CancelKeyPress += (sender, e) =>
                {
                    e.Cancel = true;
                    _logger.Info("收到停止信号，正在关闭服务...");
                    _cancellationTokenSource?.Cancel();
                };
                
                _logger.Info("控制台事件处理已设置");
            }
            catch (Exception ex)
            {
                throw new Exception($"设置控制台事件处理失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 启动DNS服务
        /// </summary>
        /// <param name="options">DNS服务选项</param>
        /// <returns>是否启动成功</returns>
        private bool StartDnsService(DnsServiceOptions options)
        {
            try
            {
                if (_dnsService == null)
                {
                    _logger.Error("DNS服务未初始化");
                    return false;
                }
                
                var config = _configManager?.LoadConfig();
                if (config == null)
                {
                    _logger.Error("无法加载配置");
                    return false;
                }
                
                _logger.Info("开始启动DNS服务");
                
                bool success = _dnsService.Start();
                
                _logger.Debug($"_dnsService.Start()返回: {success}");
                
                if (success)
                {
                    _logger.Info($"DNS服务已启动，监听端口: {config.Port}");
                    // 启动Named Pipes命令服务端（仅在服务成功启动后）
                    var dnsSvc = _dnsService as DnsService.Services.LocalDnsService;
                    var cfgMgr = _configManager as DnsService.Services.DnsConfigManager;
                    if (dnsSvc != null && cfgMgr != null)
                    {
                        _pipeServer = new DnsService.IPC.NamedPipeCommandServer(dnsSvc, cfgMgr);
                        _pipeServer.Start();
                        _logger.Info("IPC管道服务已启动，等待UI连接");
                    }
                    else
                    {
                        _logger.Warn("无法初始化IPC管道服务：类型转换失败");
                    }
                    return true;
                }
                else
                {
                    _logger.Error($"DNS服务启动失败，端口: {config.Port}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"启动DNS服务时发生错误: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 等待关闭信号
        /// </summary>
        private void WaitForShutdown()
        {
            try
            {
                // 使用取消令牌等待，而不是无限期等待事件
                if (_cancellationTokenSource != null)
                {
                    try
                    {
                        // 等待取消令牌被取消
                        _cancellationTokenSource.Token.WaitHandle.WaitOne();
                    }
                    catch (OperationCanceledException)
                    {
                        // 正常取消，不做处理
                    }
                }
                else
                {
                    // 如果没有取消令牌，使用简单的等待
                    Thread.Sleep(Timeout.Infinite);
                }
                
                _logger.Info("收到关闭信号，正在停止服务...");
            }
            catch (Exception ex)
            {
                _logger.Error($"等待关闭信号时发生错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 清理资源
        /// </summary>
        private void Cleanup()
        {
            try
            {
                _logger.Info("正在清理资源...");
                
                // 停止DNS服务
                _dnsService?.Stop();
                // 停止IPC管道服务
                _pipeServer?.Stop();
                _pipeServer = null;
                
                // 停止网络DNS监控器
                _dnsMonitor?.Stop();
                
                // 释放资源
                _dnsMonitor?.Dispose();
                _dnsService?.Dispose();
                _configManager?.Dispose();
                _cancellationTokenSource?.Dispose();
                
                _logger.Info("资源清理完成");
            }
            catch (Exception ex)
            {
                _logger.Error($"清理资源时发生错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 停止DNS服务
        /// </summary>
        public void StopService()
        {
            if (_isRunning && _dnsService != null)
            {
                _logger.Info("正在停止DNS服务...");
                _dnsService.Stop();
                _dnsService.Dispose();
                _isRunning = false;
                _logger.Info("DNS服务已停止");
            }
            
            _cancellationTokenSource?.Dispose();
        }
    }

    /// <summary>
        /// DNS服务命令行选项类
        /// 作者：huobing
        /// </summary>
        public class DnsServiceOptions
        {
            public int Port { get; set; } = 0; // 设置为0表示不使用默认值，只有明确提供-p参数时才生效
            public bool IsPortSpecified { get; set; } = false; // 标记是否明确指定了端口参数
            public List<string> UpstreamDnsServers { get; set; } = [];
            public Dictionary<string, DnsRecord> DnsRecords { get; set; } = [];
            public string? ConfigFile { get; set; }
            public string? LogFile { get; set; }
            public bool EnableConsoleLogging { get; set; } = true; // 默认启用控制台日志
        }

    /// <summary>
    /// 帮助类：提供控制台操作相关的功能
    /// </summary>
    internal static class ConsoleHelper
    {
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern IntPtr GetConsoleWindow();

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        private const int SW_HIDE = 0;
        private const int SW_SHOW = 5;

        /// <summary>
        /// 隐藏控制台窗口
        /// </summary>
        public static void HideConsoleWindow()
        {
            IntPtr consoleWindow = GetConsoleWindow();
            if (consoleWindow != IntPtr.Zero)
            {
                ShowWindow(consoleWindow, SW_HIDE);
            }
        }

        /// <summary>
        /// 显示控制台窗口
        /// </summary>
        public static void ShowConsoleWindow()
        {
            IntPtr consoleWindow = GetConsoleWindow();
            if (consoleWindow != IntPtr.Zero)
            {
                ShowWindow(consoleWindow, SW_SHOW);
            }
        }
    }

    public static class Program
    {
        private const string ServiceMutexName = "LocalDnsService.Main.Service"; // 服务唯一标识符
        private const string ServiceName = "LocalDnsService"; // Windows服务名称
        private const string ServiceDisplayName = "本地DNS服务"; // Windows服务显示名称
        private const string ServiceDescription = "提供本地DNS解析服务，支持自定义DNS记录和上游DNS服务器配置。"; // Windows服务描述

        public static int Main(string[]? args)
        {
            try
            {
                // 检查是否是Windows服务模式运行
                if (args != null && (args.Contains("--windows-service", StringComparer.OrdinalIgnoreCase) || args.Contains("-w", StringComparer.OrdinalIgnoreCase)))
                {
                    // 作为Windows服务运行
                    CreateHostBuilder(args).Build().Run();
                    return 0;
                }

                // 检查是否需要在后台运行
                bool runInBackground = args != null && (args.Contains("--background", StringComparer.OrdinalIgnoreCase) || args.Contains("-b", StringComparer.OrdinalIgnoreCase));

                bool createdNew;
                using (var mutex = new Mutex(true, ServiceMutexName, out createdNew))
                {
                    if (!createdNew)
                    {
                        // 已有实例在运行，输出提示信息并退出
                        if (!runInBackground)
                        {
                            // 这里使用Console，因为是给用户的直接提示
                            Console.WriteLine("错误：DNS服务已经在运行中！");
                            Console.WriteLine("请先停止现有服务后再启动。");
                            Console.WriteLine("按任意键退出...");
                            Console.ReadKey();
                        }
                        return 1;
                    }

                    // 如果需要在后台运行，则隐藏控制台窗口
                    if (runInBackground)
                    {
                        // 隐藏控制台窗口
                        ConsoleHelper.HideConsoleWindow();
                    }
                    else
                    {
                        // 确保控制台使用 UTF-8
                        Console.OutputEncoding = System.Text.Encoding.UTF8;
                        Console.InputEncoding = System.Text.Encoding.UTF8;
                    }

                    // 始终以服务模式运行
                    var manager = new DnsServiceManager();
                    var options = ParseServerOptions(args);
                    var ok = manager.Run(options);
                    return ok ? 0 : 1;
                }
            }
            catch (Exception ex)
            {
                // 使用Console，因为这是程序入口点的致命错误
                Console.Error.WriteLine($"Fatal error: {ex.Message}");
                return 1;
            }
        }

        /// <summary>
        /// 创建Windows服务主机构建器
        /// </summary>
        /// <param name="args">命令行参数</param>
        /// <returns>主机构建器</returns>
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseWindowsService(options =>
                {
                    options.ServiceName = ServiceName;
                })
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<LocalDnsWindowsService>();
                    services.AddSingleton<DnsServiceManager>();
                });

        private static DnsServiceOptions ParseServerOptions(string[]? args)
        {
            var options = new DnsServiceOptions();
            if (args == null || args.Length == 0) return options;
            for (int i = 0; i < args.Length; i++)
            {
                var a = args[i];
                if (string.Equals(a, "-p", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "--port", StringComparison.OrdinalIgnoreCase))
                {
                    if (i + 1 < args.Length && int.TryParse(args[i + 1], out var port) && port > 0 && port <= 65535)
                    {
                        options.Port = port;
                        options.IsPortSpecified = true;
                        i++;
                    }
                }
            }
            return options;
        }
    }
}